using Jupiter.Infrastructure.Cache.Interfaces;
using Jupiter.Infrastructure.Domain;
using Jupiter.Infrastructure.Domain.SqlSugar;
using Jupiter.Infrastructure.Domain.SqlSugar.Basic;
using Jupiter.Infrastructure.Exceptions;
using Jupiter.Infrastructure.Permission;
using Jupiter.Infrastructure.Permission.DataPermissions;
using MediatR;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Wips.AppService.Authorities.Users.Requests;
using Wips.Domain.Models.Authorities.Model;

namespace Wips.AppService.SqlSugar.Authorities.Users;

/// <summary>
/// 用户请求处理程序
/// </summary>
public class UserRequestHandler :
    RequestHandlerBase<User>,
    IRequestHandler<CreateUserRequest, string>,
    IRequestHandler<UpdateUserRequest, string>,
    IRequestHandler<DeleteUserRequest, string>,
    IRequestHandler<UserStatusChangeRequest, string>,
    IRequestHandler<UpdateUserSettingRequest, string>,
    IRequestHandler<ChangePasswordRequest, string>
{
    private readonly ISecurityContextAccessor _securityContextAccessor;

    private readonly ICacheManager _cacheManager;

    // private readonly SmsPlatformService _smsPlatform;
    private readonly IHostEnvironment _environment;
    // private readonly IWechatApiClientFactory _wechatApiClientFactory;


    /// <summary>
    /// 创建
    /// </summary>
    /// <param name="request"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public async Task<string> Handle(CreateUserRequest request,
        CancellationToken cancellationToken)
    {
        // 查询用户名是否重复
        var exists = await QueryNoTracking()
            .Where(p => p.UserName == request.UserName)
            .AnyAsync();
        // 已存在
        if (exists)
        {
            throw new CoreException("用户名已存在");
        }

        // 封装实体对象
        var entity = new User(
            request.UserName,
            request.Password,
            request.RealName,
            request.PhoneNumber,
            request.Email,
            request.Status,
            // request.UserType,
            UserId
        );
        // 新增
        await RegisterNewAsync(entity, cancellationToken);
     

        // 新增关联数据
        if (request.OrganizationIds.Count > 0)
        {
            var organizationUsers = request
                .OrganizationIds
                .Select(orgId => new OrganizationUser(orgId, entity.Id))
                .ToList();
            await RegisterNewObjectValueRangeAsync(organizationUsers, cancellationToken: cancellationToken);
        }

        // 新增关联数据
        if (request.PositionIds.Count > 0)
        {
            var positionUsers = request
                .PositionIds
                .Select(positionId => new PositionUser(positionId, entity.Id))
                .ToList();
            await RegisterNewObjectValueRangeAsync(positionUsers, cancellationToken: cancellationToken);
        }

        // 新增关联数据
        if (request.RoleIds.Count > 0)
        {
            var userRoles = request
                .RoleIds
                .Select(roleId => new UserRole(entity.Id, roleId))
                .ToList();
            await RegisterNewObjectValueRangeAsync(userRoles, cancellationToken: cancellationToken);
        }


        


        // 提交
        return entity.Id!;
    }

    /// <summary>
    /// 更新
    /// </summary>
    /// <param name="request"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public async Task<string> Handle(UpdateUserRequest request,
        CancellationToken cancellationToken)
    {
        // 查询用户名是否重复
        var exists = await QueryNoTracking()
            .Where(p => p.Id != request.Id)
            .Where(p => p.UserName == request.UserName)
            .AnyAsync();
        // 已存在
        if (exists)
        {
            throw new CoreException("用户名已存在");
        }

        // 封装实体对象
        var entity = await Query()
            .FirstOrDefaultAsync(p => p.Id == request.Id, cancellationToken);

        if (entity == null)
        {
            throw new CoreException("找不到记录");
        }

        // 更新
        entity.Update(
            request.UserName,
            request.Password,
            request.RealName,
            request.PhoneNumber,
            request.Email,
            UserId,
            IsRoot
        );



        #region 组织架构用户

        // 查询旧数据

        RegisterDeleteObjectValueRange<OrganizationUser>(p =>
            p.UserId == entity.Id);
        // 新增关联数据
        if (request.OrganizationIds.Count > 0)
        {
            var organizationUsers = request
                .OrganizationIds
                .Select(orgId => new OrganizationUser(orgId, entity.Id!))
                .ToList();
            await RegisterNewObjectValueRangeAsync(organizationUsers, cancellationToken: cancellationToken);
        }

        #endregion

        #region 职位用户

        RegisterDeleteObjectValueRange<PositionUser>(p =>
            p.UserId == entity.Id );
        // 新增关联数据
        if (request.PositionIds.Count > 0)
        {
            var positionUsers = request
                .PositionIds
                .Select(positionId => new PositionUser(positionId, entity.Id!))
                .ToList();
            await RegisterNewObjectValueRangeAsync(positionUsers, cancellationToken: cancellationToken);
        }

        #endregion

        #region 用户角色

        // 查询旧数据
        RegisterDeleteObjectValueRange<UserRole>(p =>
            p.UserId == entity.Id);

        request.RoleIds = request.RoleIds.Distinct().ToList();
        request.RoleIds = await Query<Role>()
            .Where(c => request.RoleIds.Contains(c.Id!))
            .Where(c => c.RoleType == EnumRoleType.Normal)
            .Select(c => c.Id).ToListAsync(cancellationToken); // 过滤掉特殊权限
        // 新增关联数据
        if (request.RoleIds.Count > 0)
        {
            var userRoles = request
                .RoleIds
                .Select(roleId => new UserRole(entity!.Id!, roleId!))
                .ToList();
            await RegisterNewObjectValueRangeAsync(userRoles, cancellationToken: cancellationToken);
        }

        #endregion

      

        // 更新
        RegisterDirty(entity);
        return entity.Id!;
    }

    /// <summary>
    /// 删除
    /// </summary>
    /// <param name="request"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    /// <exception cref="CoreException"></exception>
    public async Task<string> Handle(DeleteUserRequest request,
        CancellationToken cancellationToken)
    {
        if (_securityContextAccessor.UserId == request.Id)
        {
            throw new CoreException("不能删除自己.");
        }

        // 封装实体对象
        var entity = await Query()
            .FirstOrDefaultAsync(p => p.Id == request.Id, cancellationToken);
        if (entity == null)
        {
            throw new CoreException("找不到要删除的数据");
        }

        // 删除用户事件
        //entity.AddDomainEvent(new UserRemovedEvent(entity.Id));

        // 删除
        RegisterDelete(entity);
        return entity.Id!;
    }

    /// <summary>
    /// 状态变更
    /// </summary>
    /// <param name="request"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    public async Task<string> Handle(UserStatusChangeRequest request,
        CancellationToken cancellationToken)
    {
        if (_securityContextAccessor.UserId == request.Id)
        {
            throw new CoreException("不能变更自己的状态.");
        }

        // 封装实体对象
        var entity = await Query()
            .FirstOrDefaultAsync(p => p.Id == request.Id, cancellationToken);

        if (entity == null)
        {
            throw new CoreException("找不到记录");
        }

        // 变更状态
        entity.StatusChange(UserId);
        // 更新
        RegisterDirty(entity);

        return entity.Id!;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="request"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    /// <exception cref="CoreException"></exception>
    public async Task<string> Handle(UpdateUserSettingRequest request,
        CancellationToken cancellationToken)
    {
        // 封装实体对象
        var entity = await Query()
            .FirstOrDefaultAsync(p => p.Id == UserId, cancellationToken);

        if (entity == null)
        {
            throw new CoreException("找不到记录");
        }

        // 更新
        entity.UpdateBasic(
            request.RealName,
            request.PhoneNumber,
            request.Email,
            UserId
        );
        // 更新
        RegisterDirty(entity);

        return entity.Id!;
    }

    /// <summary>
    /// 修改密码
    /// </summary>
    /// <param name="request"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    /// <exception cref="CoreException"></exception>
    public async Task<string> Handle(ChangePasswordRequest request,
        CancellationToken cancellationToken)
    {
        // 封装实体对象
        var entity = await Query()
            .FirstOrDefaultAsync(p => p.Id == UserId, cancellationToken);

        if (entity == null)
        {
            throw new CoreException("找不到记录");
        }

        // 修改密码
        entity.ChangePassword(request.CurrentPassword, request.NewPassword, UserId);
        // 更新
        RegisterDirty(entity);

        return entity.Id!;
    }



    /// <summary>
    /// 
    /// </summary>
    /// <param name="dbContext"></param>
    /// <param name="securityContextAccessor"></param>
    /// <param name="facadeResolver"></param>
    /// <param name="cacheManager"></param>
    /// <param name="configuration"></param>
    /// <param name="environment"></param>
    /// <param name="dataPermission"></param>
    public UserRequestHandler(ISqlSugarClient dbContext, ISecurityContextAccessor securityContextAccessor,
        IFacadeResolver facadeResolver, ICacheManager cacheManager, IConfiguration configuration,
        IHostEnvironment environment, IDataPermission dataPermission) : base(dbContext, securityContextAccessor,
        facadeResolver, cacheManager,
        configuration, dataPermission)
    {
        _securityContextAccessor = securityContextAccessor;
        _cacheManager = cacheManager;
        _environment = environment;
    }
}